// File Transfer to Arduino.

// This program transfers files to/from an Arduino with an
//  attached SD card, which must be formatted.
// There is an accompaning Arduino sketch "File_Transfer.ino"
//  which must be loaded and running, and the Arduino must be
//  connected to the PC with a USB cable.
//  Requires QuickCalc BASIC 2.5
// Maximum path of 85 (for dirs) + / + 8.3 (filename) = 98
// Uses FAT16 naming convention
// Note - transfer is slow.  
//        Arduino SD file access is one byte ata a time.

// It is an example of and illustrates the use of the
//   following QuickCalc BASIC features:
//      Serial Files
//      Binary Files
//      The "Select" function
//      MessageBox
//      BROWSEINPUTFILE$ and BROWSEOUTPUTFILE$
//      BROWSECOMMPORTS$
//      User-defined functions
//      INPUTDIALOG
//      SORT

dim name_list$ (100)  // increase if more than 100 files in a directory.
//port$ = "COM4"  // if comm port is known and fixed
port$ = ""        // browse for port at run
speed = 19200     // must match Arduino sketch
//REC_SIZE = 65   // must match Arduino sketch
REC_SIZE = 127    // must match Ardiuno sketch
		  // REC_SIZE is smaller so Nano can have 
		  //  small buffers.
		  // For Mega2560, REC_SIZE can be 127

last_path$       = workingdir$
save_workingdir$ = workingdir$

dim dialog_array$ (1,2)
dim cmds$ (7)
  cmds$ (0) = "upload"  
  cmds$ (1) = "delete"      
  cmds$ (2) = "download" 
  cmds$ (3) = "list dir"      
  cmds$ (4) = "make dir"    
  cmds$ (5) = "delete dir"    
  cmds$ (6) = "exit"

//  debugging = 1  // (set to 1 for debug messages)
  //debug trace
  if (debugging) then print "start"

if port$ = "" then port$ = browsecommports$ ("Comm port for Arduino:")
  open serial, 4, port$, 255, speed, "NO", 1  

  delay 100  


900
  
  print
  cmd = SELECT ("Command", cmds$, 7)
  //    ******
  if cmd = -1 then goto 995 // cancelled... exit
  command$ = cmds$ (cmd)
  if debugging then print "command$ = ", command$
  if command$ = "exit"     then goto 995
  
  if cmd = 0 then nrc = upload ()
  if cmd = 1 then nrc = delete_a_file ()
  if cmd = 2 then nrc = download ()
  if cmd = 3 then nrc = list_directory ()
  if cmd = 4 then nrc = make_directory ()
  if cmd = 5 then nrc = delete_directory ()

  if (debugging) then print "return code = ";nrc

990 
  goto 900  // get another command

995 // exit
  print "EXITING"
  close 4
  end


//------------------------ UPLOAD ------------------------

def upload () = gosub 1000
1000
  // outer subr to make sure input file got closed
  rc = upload_2 ()
  close 2 // in case it is still open
  return rc

def upload_2 () = gosub 1005
1005

  if debugging = 1 then print "upload file"

// First get the source file to upload
  
  chdir last_path$
  source_full_path$ = BROWSEINPUTFILE$ ("Source file to upload:")
  last_path$ = strip_filename_from_path (source_full_path$)
  chdir save_workingdir$
 
  urc = OPEN ("input binary",  2, source_full_path$, REC_SIZE)
  if (urc = 0) then goto 1010
    beep
    print "Error opening input file"
    return -1
1010    
  // we close the file in the outer subr.

1020
  // Now get the destination path/file on the Arduino
  urc = choose_arduino (2)
  if (urc <> 1) then return -1  // error or cancel
1030
  dest_file_path$ = directory$ + new_name$

  // Before we upload it, see if it already exists and if so,
  //  do we want to overwrite it.

  urc = does_file_exist (dest_file_path$)
  if debugging then print "Return code from does_file_exist: ";nrc
  if (urc <> 1) then goto 1040
    ulrc = MESSAGEBOX ("Do you want to overwrite this file? \n" + dest_file_path$, "cancel", "retry", "OK")
    if (ulrc <> 1) then return -1 // cancel

    if (ulrc = 2) then goto 1020 // retry - pick another name
    goto 1050  // OK
1040
    if (ulrc = 2) then 
  if (urc <> 2) then goto 1050
    mdrc = MESSAGEBOX ("Directory exists with the same name.", "retry", "cancel")
    if (mdrc <> 1) then goto 1020 // retry - pick another name
      return -1  // cancel
1050
  if (urc = -1) then return -1 // [x] cancel from dialog

  print "Uploading file: "; source_full_path$
  print "to:             "; dest_file_path$

  response_to_command$ = send_command_get_response ("upload")
  if (response_to_command$ <> "OK") then return -1  

// We should have DOING_UPLOAD, state 0

  file_size = filesize (2)
  print "filesize = ", file_size

  // send a message to the Arduino with the FILE NAME (or path)

  file_open_message$ = send_command_get_response (dest_file_path$)

  // Arduino should delete and open the file
  // Arduino should respond with OK.

  if (file_open_message$ <> "OK") then return -1

  // We should have DOING_UPLOAD, state 1
  // Upload the file size

  file_size_message$ = send_command_get_response (str$(file_size))  

  // Arduino should delete and open the file ???
  // Arduino should respond with OK.

  if (file_size_message$ <> "OK") then return -1  // error

1080
  // We should have DOING_UPLOAD, state 2

  nrc = starttimer
  end_of_file = 0
  start_of_file = 1
  retry_count = 0


//--------- (UPLOAD LOOP) --------------------------------------

1100 

  // If previous transmission was an error, we will re-transmit.

  if retry_count = 0 then goto 1400 // read next record
  if retry_count < 10 then goto 1300
  // too many errors.  Cancel.

  foo$ = send_command_get_response ("-1")  

  // Arduino should cancel, close file, and respond with OK
  print "Too many Errors"
  return -1

1300 
  // retry the message
  goto 1410


1400
  line input #2, Line_read_from_file$  // read line from file

  if debugging then ?? Line_read_from_file$ // print original line
  msg_len = len (Line_read_from_file$)
  if msg_len = 0 goto 1500

  // Calculate Hash Total

  gosub 11000
  if debugging then ??  ht

1410
  // Arduino should be in DOING_UPLOAD, state 2

  // we need to upload the hash total
  ht$ = str$(ht, "MAX")

  hash_total_response$ = send_command_get_response (ht$)  

  // Arduino should save the hash total, and respond with OK

  if (hash_total_response$ <> "OK") then return -1

1420

  // Now we upload the translated line

  line_sent_response$ = send_command_get_response (Line_read_from_file$)

  // Arduino will respond with an error message or "OK"

  if line_sent_response$ = "OK" then goto 1460
    if line_sent_response$ <> "Hash Total Error" then goto 1440
      // we will retry the record
      if debugging then print "Retrying ... "
      retry_count = retry_count + 1
      goto 1100  // loop

1440 
  // Some other error
  ??  line_sent_response$
  print "Cancelling"
  return -1
  
1460
  // Record was received and written to the file
  start_of_file = 0
  retry_count = 0
  if debugging then print
  goto 1100  // loop to get next record

1500
  // we are at end-of-file.
  
  hash_total_response$ = send_command_get_response ("0")

  // response will always be OK 

  eof_response$ = send_command_get_response (Line_read_from_file$)

  // Arduino should have closed the file and responded OK

  usec = endtimer
  print "time: ", usec/1000000, " sec"

if eof_response$ <> "OK" then goto 1580
  print "File Copied Successfully"
  return 1

1580
  ?? eof_response$
  print "File Error - not copied."
  return -1

// --------------------------- DEL -------------

def delete_a_file () = gosub 4000

4000  // Delete a file
 
  // "del" - delete a file
  //  We must generate the complete path, e.g., A/B/C 
  //    where C is the file to delete.
  //  returns 1  = success
  //         -1  = error or cancel
 
if debugging then print "Delete File"

4020
  nrc = choose_arduino (1)
  if (nrc = -1) then return -1
  full_path$ = directory$ + new_name$

  // We know it is a file, 
  //  since "Choose (1) will not return a directory
  
  drc = messagebox ("Are you sure you want to delete this file? \n"     + full_path$, "Cancel", "Search Again", "OK")
  if (drc = 2) then goto 4020 // search again
  if (drc = 3) then goto 4050 // OK
    return -1  // cancel
    
4050
  print "Deleting: "; full_path$

  response_to_command$ = send_msg_get_response ("del")
  // Arduino should respond with OK.
  if (response_to_command$ = "OK") then goto 4090
    ?? response_to_command$
    return -1  // error
4090

  // send a message to the Arduino with the full path

  
  file_del_message$ = send_msg_get_response (full_path$)

//  print #4, full_path$

  // Arduino should delete the file

//  gosub 12000  // wait for Serial Input to be ready
//  line input #4, file_del_message$

  // Arduino should respond with OK.

  if (file_del_message$ = "OK") then goto 4100
    if debugging then ?? file_del_message$
    return -1

4100
  // Success deleting
  return 1  // success

//-------------------------- DOWNLOAD ---------------

def download () = gosub 5000
5000
  // outer subr to make sure output file got closed
  rc = download_2 ()
  close 3 // in case it is still open
  return rc

def download_2 () = gosub 5005
5005

  if debugging then print "Download File"
  // First get the source file on the Arduino

  drc = choose_arduino (1)
  if (drc <> 1) then return -1  // error or cancel
  source_file_path$ = directory$ + new_name$
  if debugging then ?? source_file_path$

  // Now get the destination file on the Hard Drive

5010

  chdir last_path$
  dest_file_path$ = BROWSEOUTPUTFILE$ ("Select Destination File:")
  last_path$ = strip_filename_from_path (dest_file_path$)
  chdir save_workingdir$

  // See if the file already exists - try to open it
  drc = OPEN ("input", 3, dest_file_path$)
  close 3
  if (drc < 0) then goto 5020  // file not found (open failed)
    drc = MESSAGEBOX ("File " + dest_file_path$ + "\n already exists.", "Overwrite", "Re-Select", "Cancel")
    if (drc = 1) then goto 5020 // overwrite
    if (drc = 2) then goto 5010 // re-select
    return -1  // cancel

5020
  print "Downloading: ";source_file_path$
  print "to:          ";dest_file_path$

  response_to_command$ = send_command_get_response ("download")
  if (response_to_command$ <> "OK") then return -1

  // We should have DOING_DOWNLOAD, state 0

  drc = starttimer

  // send a message to the Arduino with the full file path

  file_open_message$ = send_msg_get_response (source_file_path$)

  // Arduino should open the file and respond with file size.
  if debugging then ?? file_open_message$  // = file size

  arduino_file_size = val (file_open_message$)
  if debugging then ?? arduino_file_size

  if arduino_file_size >= 0 then goto 5100
    print "File Does Not Exist"  // should not occur
    return -1
5100
  drc = OPEN ("output binary", 3, dest_file_path$, REC_SIZE)
  if (drc = 0) then goto 5110
    print "Could not open output file " + dest_file_path$
    foo$ = send_msg_get_response ("cancel")  // cancel the download
    return -1
5110

  // Respond OK so Arduino will begin to send file

  print #4, "OK"
  retry_count = 0

5130
  // Now Arduino is in state 2

  gosub 12000  // wait for Serial Input to be ready
  line input #4, hash_total_message$
  if debugging then ?? hash_total_message$
  arduino_hash_total = val (hash_total_message$)

  // respond OK to hash total message
  print #4, "OK"

  // Now Arduino goes to state 3

  gosub 12000  // wait for Serial Input to be ready
  line input #4, Line_read_from_file$
  if debugging then ?? line_read_from_file$
  msg_len = len (Line_read_from_file$)

  // Check for end-of-file

  if msg_len = 0 then goto 5300
    

  // Calculate hash total on received line
  gosub 11000
  if debugging then print "Calculated hash total: ", ht
  
  // compare hash totals

  if (arduino_hash_total = ht) then goto 5200
    // hash total (checksum) error
    print "checksum error"
    retry_count = retry_count + 1
    if (retry_count < 10) then goto 5150
      // too many retries.  Cancel.
      print "Failed after 10 retries.  Cancelling."
      close 3
      download_cancel$ = send_msg_get_response ("cancel")
      if debugging then ?? download_cancel$
      return -1
5150
    // we are going to retry the transmission
    print #4, "retry"
    goto 5130

5200
  // Checksums compare OK
  retry_count = 0
  // Write translated message to file
  print #3, Line_read_from_file$
  
  print #4, "OK"
  goto 5130

5300

  // zero-length record = end-of-file
  // no further interaction with Arduino.
  // Arduino goes to IDLE
  close 3
  // received file is complete. 
  
  // verify size
  open input, 3, dest_file_path$  // re-open file
  file_size = filesize (3)
  if debugging then print "new file size = ", file_size 
  close 3
  if (arduino_file_size = file_size) goto 5400
    print "Total file size does not compare." 
    beep
    return -1
    // We should probably delete the bad file. 
   
5400 
  print "Download Successful." 
  usec = endtimer
  print "time: ", usec/1000000, " sec"
  return 1

//---------------------------- DIR -------------------

def list_directory () = gosub 6000
6000	// "dir"
  if debugging then print "List Directory"
  first_file = 0
  directory$ = "/"
  nrc = choose_arduino (3)
  if (nrc = -1) then return -1
  print "Directory list for: "; directory$
  response_to_command$ = send_msg_get_response ("dir")
  // Arduino should respond with OK.
  if (response_to_command$ = "OK") then goto 6090
    ?? response_to_command$
    return -1  // error
6090
  if debugging then ?? directory$
  print #4, directory$   // give Arduino the path of the directory
6100
  gosub 12000
  line input #4, line$
  if line$ = "bad path" then ? "bad path": goto 990
  if line$ = "done!" then goto 6200
  first_file = 1
  if right$(line$, 1) = "/" then goto 6150  // directory
    input %line$, filename$, filesizex
    print using "##,###,###"; filename$, filesizex
    goto 6170
6150
    print line$
6170

  print #4, "OK"
  goto 6100  // loop reciving filenames

6200 // no more files
  if first_file = 0 then print "<---empty--->": return 0   print "---end of list---"
  return 0

//---------------------------- MKDIR -------------

def make_directory () = gosub 7000
7000 
  if debugging then print "mkdir"
  // "mkdir" - create a directory
  //  We must generate the complete path, e.g., A/B/C 
  //    where C is the new directory.

7020
  nrc = choose_arduino (4)
  if (nrc = -1) then return -1
  full_path$ = directory$ + new_name$
  ?? full_path$

  // path for mkdir must be 1 shorter than Create" allows
  // because a / is added at the end when you try to delete it.
? len (full_path$)
  if len (full_path$) < 86 then goto 7030
    beep
    rc = messagebox ("Path is too long", "OK")
    return -1
7030
  // Before we try to create the directory, let's check if
  // it already exists, or conflicts with a file name.
 
  nrc = does_file_exist (full_path$)
  //print "Return code from does_file_exist: ";nrc
  if (nrc <> 1) then goto 7070
    mdrc = messagebox ("Proposed directory name conflicts with an " + "existing file name.", "retry", "cancel")
    if (mdrc = 1) then goto 7020 else return -1
7070
  if (nrc <> 2) then goto 7080
    mdrc = messagebox ("Directory already exists.", "retry", "cancel")
    if (mdrc = 1) then goto 7020 else return -1
7080
  if (nrc = -1) then return -1

  // Now neither the dir. or file with same name exists.
  print "Creating directory: "; full_path$

  response_to_command$ = send_msg_get_response ("mkdir")
  // Arduino should respond with OK.
  if (response_to_command$ = "OK") then goto 7090
    ?? response_to_command$
    return -1  // error
7090

    
  // send a message to the Arduino with the path+directory_name

  mkdir_message$ = send_msg_get_response (full_path$)
  // Arduino should create the directory and respond "OK" or "Error"
  print mkdir_message$
  if (mkdir_message$ <> "OK") then return -1
  print "mkdir successful"
  return 0

//---------------------------- RMDIR -------------

def delete_directory () = gosub 8000
8000 
  if debugging then print "Delete Directory"
  // "rmdir" - delete a directory
  //  Directory must be empty or this will fail.
  //  We must supply the complete path, e.g., A/B/C 
  //    where C is the directory to remove.

8020
  nrc = choose_arduino (3)
  if (nrc = -1) then return -1

  // Before we try to delete the directory, let's check if
  // it exists, and actually is a directory.
 
  rdrc = does_file_exist (directory$)
  //print "Return code from does_file_exist: "; rdrc
  if (rdrc <> 1) then goto 8070
    rdrc = messagebox ("Name specified is not a directory " , "retry", "cancel")
    if (rdrc = 1) then goto 8020 else return -1
8070
  if (rdrc <> 0) then goto 8080
   rdrc = messagebox ("Directory does not exist.", "retry", "cancel")
    if (rdrc = 1) then goto 8020 else return -1
8080
  if (rdrc = -1) then return -1 // error - user exited messagebox

  // Now we know the directory exists and is valid.

  // we must verify that the directory is empty before trying
  // to delete it.

  rdrc = is_directory_empty (directory$)
  //  0 = not empty, 1 = empty
  if (rdrc = 1) then goto 8085
    rdrc = messagebox ("Directory is not empty.", "retry", "cancel")
    if (rdrc = 1) then goto 8020 else return -1

8085  
  print "Deleting directory: "; directory$

  response_to_command$ = send_msg_get_response ("rmdir")
  // Arduino should respond with OK.
  if (response_to_command$ = "OK") then goto 8090
    ?? response_to_command$
    return -1  // error
8090

  // send a message to the Arduino with the Directory name

//  input "Directory to Remove (full path):", remove_path$
//  print #4, remove_path$
  rmdir_message$ = send_msg_get_response (directory$)
  // Arduino should remove the directory and respond "OK" or "Error"
//  
//  gosub 12000  // wait for Serial Input to be ready
//  line input #4, rmdir_message$
  //print rmdir_message$
  if rmdir_message$ = "OK" then return 1 else return -1

//---------------------------- CHOOSE -------------------

def choose_arduino (mode) = gosub 9000
9000	// "choose"
  // mode =   1 select a file to download or delete
  //            (must exist already)
  //          2 select a file to upload / create (new or existing)
  //          3 select a directory to delete or list
  //          4 select a directory to create
  // returns  1 if successful
  // returns -1 if error 
  // returns  0 if user cancelled
  // filename selected is in new_name$
  // path selected is in     directory$

  if debugging then print "Choose"
  dir_cmd$ = "dir"
  if (mode = 3 or mode = 4) then  dir_cmd$ = "dird"  // just show directories

  if debugging then ?? dir_cmd$
  response_to_command$ = send_msg_get_response (dir_cmd$)
  // Arduino should respond with OK.
  if (response_to_command$ = "OK") then goto 9060
    ?? response_to_command$
    return -1  // error

9060
  first_file = 0	// ??
  directory$ = "/"	// start at root
  
9100
  if debugging then ?? directory$
  print #4, directory$   // give Arduino the path of the directory
  i = 0
  // put "dummy" first entry of ".." into list.
  if directory$ = "/" goto 9110 // no "back 1 directory" for root
    name_list$ (i) = " .. " // leading space sorts first
    i = i + 1
9110
  if mode <> 3 then goto 9120
    name_list$ (i) = " [select this directory]"
    i = i + 1
9120
  if mode <> 2 then goto 9130
    name_list$ (i) = " [new file in this directory]"
    i = i + 1
9130
  if (mode <> 4) then goto 9140
    name_list$ (i) = " [new directory (here)]"
    i = i + 1
9140
  if debugging then ?? i
  if debugging then ? "name_list$ (i) = ";name_list$(i)
  gosub 12000
  line input #4, line$
  if debugging then ?? line$
  if left$(line$, 8) <> "bad path" then goto 9141
    ? "bad path" 
    ? line$ 
    return -1
9141
  if line$ = "done!" then goto 9200
  first_file = 1
  if  right$ (line$, 1) = "/" then goto 9150  // directory
    // we have a file name
    // if we are just looking for a directory (to delete or create)
    // we will not add the file name top the list.
    if (mode = 3 OR mode = 4) then goto 9142
      input %line$, filename$, filesizex
      //print %line$; using "##,###,###"; filename$, filesizex
      //print line$
      name_list$ (i) = filename$  // put file name into array
      i = i + 1
9142
    goto 9170
    
9150 // directory
    //print line$
    length = len (line$)
    name_list$ (i) = "+" + mid$ (line$, 1, length-1)
    i = i + 1
9170

  print #4, "OK"
  goto 9140  // loop reciving filenames

9200 // no more files
  if debugging then print "no more files"
  if first_file = 0 then print "<---empty--->": return -1 //??
     
9250
  // ? i
  if (i >= 2) then sort name_list$, count=i
  directory2$ = directory$
  if (len (directory2$) > 28) then directory2$ = left$ (directory2$, 28) + "\n" + mid$ (directory2$, 29, 255) // split
  if (len (directory2$) > 55) then directory2$ = left$ (directory2$, 55) + "\n" + mid$ (directory2$, 56, 255) // split
  if (len (directory2$) > 82) then directory2$ = left$ (directory2$, 82) + "\n" + mid$ (directory2$, 83, 255) // split
i = select ("choose file or directory\n"+directory2$, name_list$, i)
  //  ******
  if i >= 0 then goto 9300
    print "user cancelled"  // ??
    return -1
9300
  new_name$ = name_list$ (i)
  if left$ (new_name$, 1) <> "+" then goto 9310
    new_name$ = mid$ (new_name$, 2, 100) + "/"
9310
  if left$ (new_name$, 2) <> " [" then goto 9320
    if (mode <> 3) then goto 9315
      // [select this directory]
      new_name$ = ""
9315
    if (mode <> 2) then goto 9318
      // [new file]
      dialog_array$ (0,1) = "File Name"
      dialog_array$ (0,0) = "new_name$"
      rc = inputdialog ("Enter file name to upload to",dialog_array$)
      //   ***********
      if rc < 0 then return -1
      // (we might want to edit the file name here)
      goto 9330
9318
    if (mode <> 4) then goto 9320
      // [new directory (here)]
      dialog_array$ (0,1) = "Directory Name"
      dialog_array$ (0,0) = "new_name$"
      rc = inputdialog ("Enter new directory to create", dialog_array$)
      //   ***********
      if rc < 0 then return -1
      // (we might want to edit the directory name here)
      goto 9330
9320    
// If the user selected a directory then we will 
//  search that directory. The selected directory
//  name is added to the current path.

  if new_name$ <> " .. " goto 9330
  //print "backup button selected"
9325
  j = len (directory$)
  if right$ (directory$, 1) = "/" then j = j - 1
  while j > 0
    if mid$ (directory$, j, 1) = "/" then break
    j = j - 1
  wend
  if j > 0 then directory$ = left$ (directory$, j) else directory$="/"
  goto 9380
9330
  if right$(new_name$, 1) = "/" then goto 9350  // directory
    // no, was a file.
    if debugging then print "file selected was ", new_name$
    if debugging then print "path selected was ", directory$
    return 1
9350
  if directory$ = "/" then directory$ = "": goto 9370  
  if right$ (directory$, 1) = "/" then goto 9370
    directory$ = directory$ + "/"
9370
  directory$ = directory$ + new_name$
  if len (directory$) < 87 then goto 9380
  if (mode = 1 or mode = 2) then goto 9380 //OK if selecting file
    beep
    rc = messagebox ("Path is too long", "OK")
    goto 9325  // backup
9380
  if debugging then print "searching "; directory$
  response_to_command$ = send_msg_get_response (dir_cmd$)
  // Arduino should respond with OK.
  if (response_to_command$ = "OK") then goto 9360
    print response_to_command$
    return -1
9360  
  goto 9100


//------------------------See if file exists ----------------

def does_file_exist (file_spec$) = gosub 9500
9500  
  // see if file (or directory) exists
  // checks directory$ / new_name$
  // returns: 0 = not found (does not exist)
  //          1 = file exists
  //          2 = it is an existing directory

  response_to_command$ = send_msg_get_response ("exists")
  // Arduino should respond with OK.
  if (response_to_command$ = "OK") then goto 9560
    ?? response_to_command$
    return -1

9560
  // send a message to the Arduino with the FILE NAME (or path)

  //full_path$ = directory$ + new_name$
  //print "checking for: "; file_spec$
  file_exists_message$ = send_msg_get_response (file_spec$)

  // Arduino should respond with 1="File Exists", 0="No File" 2="Dir"

  //? file_exists_message$ // print response 
  if (file_exists_message$ = "1") then return 1
  if (file_exists_message$ = "0") then return 0
  if (file_exists_message$ = "2") then return 2
  return -1 // (error ??)

//===============================================

def is_directory_empty (dir$) = gosub 9700
9700

  //print "checking if empty "; dir$
  response_to_command$ = send_msg_get_response ("dir")
  // Arduino should respond with OK.
  if (response_to_command$ = "OK") then goto 9760
    //?? response_to_command$
    return -1  // error
9760 
  // send Arduino the path of the directory
  line$ = send_msg_get_response (dir$)
  if line$ = "bad path" then ? "bad path": return -1
  if line$ = "done!" then return 1  // directory is empty
  // if we didn't get "done!" then we are still in "dir
  // mode and we need to cancel out of it.
  response_to_command$ = send_msg_get_response ("cancel")
  return 0 // directory is not empty

//=================================================

11000
// Calculate Hash Total
ht = 0
for i = 1 to msg_len
  c$ = mid$ (Line_read_from_file$, i, 1)
  a = asc (c$)
  m = a * i
  ht = ht + m
//  print i, c$, a, m, ht 
next
return

//---------------------------
12000   // Wait until input message is availalble
12820 
  msg_avail = input (4)
  if (not msg_avail)  goto 12820  // loop until msg avail
  return
  //while (not input (4))
  //wend

//---------------------------

def send_command_get_response (command$) = gosub 13000
13000
  // Use this routine when the expected response is "OK"
  // send a message to the Arduino with the COMMAND
  if debugging then ?? command$

  response_to_command$ = send_msg_get_response (command$)

  // Arduino should respond with OK.
  if (response_to_command$ = "OK") then goto 13080
    ?? response_to_command$ // some kind of error

13080
  return response_to_command$

// --------------------------------------------------

def send_msg_get_response (send_msg$) = gosub 15000
15000
// send a message to the Arduino 
  print #4,send_msg$	// Send message to Arduino
  gosub 12000           // wait for Serial Input to be ready
  line input #4, response$    
  if debugging then print "response to ";send_msg$; " = "; response$ 
  return response$

//-----------------------------------------------------	

def strip_filename_from_path (path$) = gosub 16000
16000
// The user has selected a path\filename from BROWSEINPUTFILE$ or
//  BROWSEOUTPUTFILE$.  We want to know the path so the next time
//  we browse, we can start in that directory (saving time).
  pathlen = len(path$)
  while pathlen > 0
    if (mid$(path$, pathlen, 1) = "\\") then break
    pathlen = pathlen - 1
  wend
  // we are on the \ char or at the start of the string.
  if (pathlen = 0) then pathlen = 1  // should not occur
  return left$ (path$, pathlen-1)
